using System;
using UnityEngine;
#if ODIN_INSPECTOR
using Sirenix.OdinInspector;
#endif
namespace Common.DataType
{
    public enum Logic 
    {
        Any,
        All,
    }


    /// <summary>
    /// 区间
    /// </summary>
    /// 
    [Serializable]
    public abstract class Interval<T> where T : struct
    {
        public enum EndPointType
        {
            Close_Open,
            Close_Close,
            Open_Open,
            Open_Close,
        }
        [SerializeField]
        private T _min;
        [SerializeField]
        private T _max;
        [SerializeField]
        private EndPointType _endPointType;
        public Interval()
        {

        }
        public Interval(T min, T max, EndPointType endType = EndPointType.Close_Open)
        {
            _min = min;
            _max = max;
            _endPointType = endType;
        }
 
        public T Min { get => _min; set => _min = value; }
        public T Max { get => _max; set => _max = value; }
        public EndPointType EndType { get => _endPointType; }
    }
    [Serializable]
    public class FloatInterval : Interval<float>
    {
        public FloatInterval()
        {
        }

        public FloatInterval(float min, float max, EndPointType endType = EndPointType.Close_Open) : base(min, max, endType)
        {
        }
    }
    [Serializable]
    public class IntInterval : Interval<int>
    {
        public IntInterval()
        {
        }

        public IntInterval(int min, int max, EndPointType endType = EndPointType.Close_Open) : base(min, max, endType)
        {
        }
    }
    public static class IntervalEx
    {
        /// <summary>
        /// 元素value在区间内
        /// </summary>
        /// <param name="interval"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool InRange(this Interval<float> interval , float value)
        {
            switch (interval.EndType)
            {
                case Interval<float>.EndPointType.Close_Open:
                    return interval.Min <= value && value < interval.Max;
                case Interval<float>.EndPointType.Close_Close:
                    return interval.Min <= value && value <= interval.Max;
                case Interval<float>.EndPointType.Open_Open:
                    return interval.Min < value && value < interval.Max;
                case Interval<float>.EndPointType.Open_Close:
                    return interval.Min < value && value <= interval.Max;
                default:
                    return false;
            }
        }
        public static bool InRange(this Interval<int> interval, int value)
        {
            switch (interval.EndType)
            {
                case Interval<int>.EndPointType.Close_Open:
                    return interval.Min <= value && value < interval.Max;
                case Interval<int>.EndPointType.Close_Close:
                    return interval.Min <= value && value <= interval.Max;
                case Interval<int>.EndPointType.Open_Open:
                    return interval.Min < value && value < interval.Max;
                case Interval<int>.EndPointType.Open_Close:
                    return interval.Min < value && value <= interval.Max;
                default:
                    return false;
            }
        }
    }
}